package com.codebox.knowledge.rxjava.operator;

import android.widget.TextView;

import com.codebox.common.util.LogUtils;
import com.codebox.knowledge.rxjava.bean.Student;
import com.codebox.knowledge.rxjava.bean.Teacher;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * map操作符，主要是对集合中的元素进行单独操作，逻辑简洁
 *
 * @author 李立
 * @date 2018/12/31
 */
public class Rxjava2Map {

    //好学生得数量
    private int mGoodNum;

    private TextView mTvLog;

    public Rxjava2Map(TextView textView){
        this.mTvLog = textView;
    }

    /**
     * flatMap 操作符 接收事件的顺序和发送得事件的顺序可能不同
     * flatmap 可以连续使用
     */
    public void flatMapMethod() {

        mTvLog.setText("");
        List<Student> students = new ArrayList<>();
        students.add(new Student("LHD1", 60));
        students.add(new Student("LHD2", 70));
        students.add(new Student("LHD3", 80));
        students.add(new Student("LHD4", 90));
        students.add(new Student("LHD5", 100));

        //Observable.fromIterable(students): 后续的操作接收到的数据是List<Student>
        //Observable.just(students);         后续的操作接收到的数据是Student。

        Disposable subscribe = Observable.just(students)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .flatMap(new Function<List<Student>, ObservableSource<Teacher>>() {
                    @Override
                    public ObservableSource<Teacher> apply(List<Student> students1) throws Exception {
                        Teacher teacher = new Teacher();
                        teacher.setName("笨老师");
                        teacher.setGood(false);
                        for (Student s : students1) {
                            if (s.getScore() > 90) {
                                ++mGoodNum;
                                teacher.setName("好老师");
                                teacher.setGood(true);
                                teacher.setGoodNum(mGoodNum);
                            }
                        }
                        //在这里传出teacher,
                        return Observable.just(teacher);
                    }
                })
                //在这接收teacher,然后拿到teacher中的信息做出处理，将新数据str 发送出去，
                //然后再subscribe方法中接收这个str。
                .flatMap(new Function<Teacher, ObservableSource<String>>() {
                    @Override
                    public ObservableSource<String> apply(Teacher teacher) throws Exception {
                        String teacherGoodString = "";
                        teacherGoodString = teacher.getGoodNum() >= 2 ? "好" : "不好";
                        String str = "这个 " + teacher.getName() + " good 不？" + teacherGoodString;
                        return Observable.just(str);
                    }
                })
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
//                        LogUtils.e("Rxjava2Map:", s);
                        mTvLog.append("Rxjava2Map:"+ s + "\n" +"\n");
                    }
                });
    }

    /**
     * concatMap操作符发送事件的顺序和接收事件的顺序相同
     */
    public void concatMap() {
        mTvLog.setText("");

        List<Student> students = new ArrayList<>();
        students.add(new Student("LHD1", 60));
        students.add(new Student("LHD2", 70));
        students.add(new Student("LHD3", 80));
        students.add(new Student("LHD4", 90));
        students.add(new Student("LHD5", 100));

//        Observable.fromIterable(students): 后续的操作接收到的数据是List<Student>
//        Observable.just(students);         后续的操作接收到的数据是Student。

        Disposable subscribe = Observable.just(students)

                //第一个List<Student> 是传进来的数据源， 第二个List<Student> 是我们要发出去的数据。
                //第二个List<Student> 的数据类型我们自己定义，需要什么写什么。
                //concatMap 中的操作： 将分数大于等于90 的学生放到新的集合中，然后发送出去。
                //发送出去之后在subscribe方法中收到刚刚在concatMap方法中发送出去的学生集合。
                .concatMap(new Function<List<Student>, ObservableSource<List<Student>>>() {
                    @Override
                    public ObservableSource<List<Student>> apply(List<Student> students1) throws Exception {

                        ArrayList<Student> list2 = new ArrayList<>();

                        int student1Size = students1.size();
                        for (int i = 0; i < student1Size; i++) {
                            Student student = students1.get(i);
                            int score = student.getScore();
                            if (score >= 90) {
                                list2.add(student);
                            }
                        }
                        return Observable.just(list2);
                    }
                })
                .subscribe(new Consumer<List<Student>>() {
                    @Override
                    public void accept(List<Student> students12) throws Exception {

                        int student2Size = students12.size();
                        if (student2Size >= 2) {
//                            LogUtils.e("Rxjava2Map:accept:好老师");
                            mTvLog.append("Rxjava2Map:accept:好老师" + "\n"+"\n");
                        } else {
//                            LogUtils.e("Rxjava2Map:accept:坏老师");
                            mTvLog.append("Rxjava2Map:accept:坏老师" + "\n"+"\n");
                        }
                    }
                });
    }

}
